package com.game.play;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import com.game.cards.Attribute;
import com.game.cards.BaseCard;
import com.game.cards.Flags;
import com.game.cards.MonsterCard;
import com.game.cards.SpellCard;
import com.game.cards.TrapCard;
import com.game.cards.Type;

public class Field {
	private ArrayList<MonsterCard> monsterSlots;
	private ArrayList<BaseCard> spellTrapSlots;
	private List<BaseCard> graveyard;
	private ActionQueue aq;
	private Player owner;
	
	public Field(ActionQueue aq, Player owner)
	{
		this.monsterSlots = new ArrayList<MonsterCard>(5);
		this.spellTrapSlots = new ArrayList<BaseCard>(5);
		this.graveyard = new ArrayList<BaseCard>();
		this.aq = aq;
		this.owner = owner;

	}
	public void playCard(BaseCard c)
	{
		if (c instanceof MonsterCard) normalSummon((MonsterCard)c);
		else if (c instanceof TrapCard) {

			setTrapCard(c);
		}
		else if (c instanceof SpellCard) playSpellCard(c);
	}
	public boolean setTrapCard(BaseCard c)
	{
		if (spellTrapSlots.add(c))
		{
	
			aq.addTrap((TrapCard)c);
			aq.addEvent(Events.settrap.toString() + ","+Integer.toString(c.getId()));
			this.owner.getHand().getGame().getCurrentTurn().getHand().removeCardById(c.getId());
			return true;
		}
		return true;
	}
	public boolean playSpellCard(BaseCard c)
	{
		if (spellTrapSlots.add(c))
		{
		
			aq.addEvent(Events.usespell.toString() + ","+Integer.toString(c.getId()));
			((SpellCard)c).effect(this.owner.getCurrentDeck().getGame());
			this.owner.getHand().getGame().getCurrentTurn().getHand().removeCardById(c.getId());
			return true;
		}
		return true;
	}
	public boolean normalSummon(MonsterCard m)
	{
		if (m.getTributes() > 0) this.tributeSummon(m);
		else if (monsterSlots.add(m)) {
		if (m.getFlags().contains(Flags.effect) && m.getFlags().contains(Flags.triggereffect))aq.addEffect(m);
		this.owner.getHand().getGame().getCurrentTurn().getHand().removeCardById(m.getId());
		aq.addEvent(Events.normalsummon.toString() +","+Integer.toString(m.getId()) + "," + this.owner.getName());
		return true;
		}
		return false;
	}
	public void specialSummon(MonsterCard m)
	{
		monsterSlots.add(m);
		if (m.getFlags().contains(Flags.effect) && m.getFlags().contains(Flags.triggereffect))aq.addEffect(m);
		aq.addEvent(Events.specialsummon.toString() +","+Integer.toString(m.getId()));
	}
	public boolean tributeSummon(MonsterCard m)
	{
		int amount = m.getTributes();
		List<MonsterCard> del = new ArrayList<MonsterCard>();
		if (this.getMonsterCards().size() >= amount) {
			while (amount > 0) {
			System.out.println("Which cards will you sacrifice to summon " + m.getTitle() + "?");
			System.out.println(amount + " remaining.");
			System.out.println("Type -1 to cancel");
			Scanner scan = new Scanner(System.in);
			int i = 0;
			for (MonsterCard mc : this.getMonsterCards())
			{
				if (!del.contains(mc)) {System.out.println("(" + i + ")" + mc.getTitle());
				}
				i++;
			}
			int input = scan.nextInt();
			if (input != -1) {
				del.add(this.getMonsterCards().get(input));
				amount--;
			}
			else if (input == -1)
			{
				return false;
			}
			}
		this.owner.getHand().getGame().getCurrentTurn().getHand().removeCardById(m.getId());
		this.monsterSlots.removeAll(del);
		this.aq.getEffects().removeAll(del);
		this.graveyard.addAll(del);
		for (MonsterCard mc : del)
		{
			this.aq.addEvent(Events.destroycard +","+ mc.getId());
		}
		if (m.getFlags().contains(Flags.effect) && m.getFlags().contains(Flags.triggereffect))aq.addEffect(m);
		monsterSlots.add(m);
		aq.addEvent(Events.tributesummon.toString() +","+Integer.toString(m.getId()));
		}
		return false;
	}
	public void attackMonster(MonsterCard t, MonsterCard a)
	{
		//Game temp = this.owner.getCurrentDeck().getGame();
		
		aq.addEvent(Events.attackmonster.toString() + "," +Integer.toString(t.getId()) + "," + 
		Integer.toString(a.getId()));
	}
	public void attackPlayer(Player t, MonsterCard a)
	{
		aq.addEvent(Events.attackplayer.toString() + "," + t.getName() + "," + Integer.toString(a.getId()));
	}
	public List<MonsterCard> getMonsterCards()
	{
		List<MonsterCard> temp = new ArrayList<MonsterCard>();
		for (MonsterCard c : this.monsterSlots)
		{
			if (c instanceof MonsterCard)
			{
				temp.add(c);
			}
		}
		return temp;
	}
	public List<MonsterCard> getMonsterCards(Type type)
	{
		List<MonsterCard> temp = new ArrayList<MonsterCard>();
		for (MonsterCard c : this.monsterSlots)
		{
			if (c instanceof MonsterCard)
			{
				if (c.getType() == type)temp.add(c);
			}
		}
		return temp;
	}
	public List<MonsterCard> getMonsterCards(Attribute attr)
	{
		List<MonsterCard> temp = new ArrayList<MonsterCard>();
		for (MonsterCard c : this.monsterSlots)
		{
			if (c instanceof MonsterCard)
			{
				if (c.getAttribute() == attr)temp.add(c);
			}
		}
		return temp;
	}
	
	public List<MonsterCard> getEffectMonsterCards()
	{
		List<MonsterCard> temp = new ArrayList<MonsterCard>();
		for (MonsterCard c : this.monsterSlots)
		{
			if (c instanceof MonsterCard)
			{
				if (c.getFlags().contains(Flags.effect) && !c.getFlags().contains(Flags.triggereffect))temp.add(c);
				
			}
		}
		return temp;
	}
	public List<BaseCard> getSpellTrapCards()
	{
		List<BaseCard> temp = new ArrayList<BaseCard>();
		for (BaseCard c : this.spellTrapSlots)
		{
			if (c instanceof SpellCard)
			{
				temp.add(c);
			}
		}
		return temp;
	}
	public List<BaseCard> getGraveyard()
	{
		return this.graveyard;
	}
	public boolean removeMonsterById(int id)
	{
		for (BaseCard c : this.monsterSlots)
		{
			if (c.getId() == id) {
				this.monsterSlots.remove(c);
				this.graveyard.add(c);
				return true;
			}
		}
		return false;
	}
	public boolean removeSpellTrapById(int id)
	{
		for (BaseCard c : this.spellTrapSlots)
		{
			if (c.getId() == id) {
				this.spellTrapSlots.remove(c);
				return true;
			}
		}
		return false;
	}
}
